package ro.ciacob.utils {
	import flash.utils.ByteArray;

	public final class Arrays {

		/**
		 * Randomizes in-place the given array.
		 * @param 	array
		 * 			The array to randomize.
		 */
		public static function shuffle(array:Array):void {
			var randomSort:Function = function(a:Object, b:Object):int {
				return (Math.random() > 0.5) ? 1 : -1;
			}
			array.sort(randomSort);
		}
		
		/**
		 * Tests whether two arrays that only contain primitives (Numbers, ints, uints, 
		 * Booleans, Strings) are identical after being sorted.
		 * 
		 * @param	arrayA
		 * 			The first array to compare.
		 * 
		 * @param	arrayB
		 * 			The second array to compare.
		 * 
		 * @return	True if arrays are identical (contain each, the same values).
		 * 			Note: this function modifies your arrays (sorts them in place).
		 */
		public static function sortAndTestForIdenticPrimitives(arrayA:Array, arrayB:Array):Boolean {
			arrayA.sort();
			arrayB.sort();
			return (arrayA.join('') == arrayB.join(''));
		}
		
		/**
		 * Tests whether two arrays are identical (same number items, all of which 
		 * pass the equality test (`==`) and the proper order test (first item in A
		 * must equal first item in B, and so forth). 
		 * 
		 * The arrays are not modified durring the test. The arrays need not only 
		 * contain primitives (as opposed to `sortAndTestForIdenticPrimitives`).
		 * 
		 * @param	arrayA
		 * 			The first array to compare.
		 * 
		 * @param	arrayB
		 * 			The second array to compare.
		 * 
		 * @return	True if arrays are identical, false otherwise. Returns false if
		 * 			either of the arguments is null (even if both are).
		 */
		public static function testForIdentity (arrayA:Array, arrayB:Array) : Boolean {
			if (arrayA == null) {
				return false;
			}
			if (arrayB == null) {
				return false;
			}
			if (arrayA.length != arrayB.length) {
				return false;
			}
			for (var i:int = 0; i < arrayA.length; i++) {
				if (arrayA[i] != arrayB[i]) {
					return false;
				}
			}
			return true;
		}
		
		/**
		 * Removes dupplicate elements within a given array. Modifies the array in 
		 * place, and does not sort it. The equality test employed is `==`.
		 * 
		 * @param	array
		 * 			The array to remove dupplicates from. 
		 */
		public static function removeDupplicates (array : Array) : void {
			// TODO: TEST THIS CODE
			if (array != null && array.length > 0) {
				var tmp : Array = array.concat();
				array.splice(0);
				for (var i:int = 0; i < tmp.length; i++) {
					var el : Object = tmp[i];
					if (array.indexOf(el) == -1) {
						array.push (el);
					}
				}
			}
		}
		
		/**
		 * Performs a deep clone operation of an array that contains basic types,
		 * such as boolean, int, uint, number, string, array, object.
		 * 
		 * Important: if the array contains custom types, they will loose their type
		 * (although you might still be able to access their methods and properties).
		 * Using `registerClassAlias` & friends might help with that issue.
		 * 
		 * @param	array
		 * 			The array to be deeply cloned.
		 * 
		 * @return	A deep clone of the original array.
		 */
		public static function deepCloneArrayOfBasicTypes (array : Array) : Array {
			var myBA:ByteArray = new ByteArray; 
			myBA.writeObject(array);
			myBA.position = 0;
			return (myBA.readObject() as Array); 		
		}
	}
}
